import { Box, Flex, Image, IconButton, ButtonGroup } from '@chakra-ui/react';
import PointerTracker, { Pointer, InputEvent } from 'pointer-tracker';
import PinchZoom from './PinchZoom';
import {
  useRef,
  useEffect,
  PointerEvent,
  MouseEvent,
  TouchEvent,
  WheelEvent,
  useState,
} from 'react';
import {
  BiRotateLeft,
  BiRotateRight,
  BiZoomIn,
  BiZoomOut,
} from 'react-icons/bi';
import leftImage from '../../assets/images/5.jpg';
import rightImage from '../../assets/images/6.jpg';
import { $splitPoint } from '../store';

type Event = MouseEvent | TouchEvent | PointerEvent | WheelEvent;

type TwoUpOrientation = 'horizontal' | 'vertical';

type PinchZoomRefType = {
  _onScale: (s: number) => void;
  _rotate: (r: number) => void;
  _onWheel: (e: WheelEvent) => void;
  _onPointerMove: (pp: Pointer[], cp: Pointer[]) => void;
};

export default function TwoUp({
  orientation = 'horizontal',
}: {
  orientation?: TwoUpOrientation;
}) {
  const twoUpRef = useRef<HTMLDivElement | null>(null);
  const twoUpHandleRef = useRef<HTMLDivElement | null>(null);
  const pinchZoomLeft = useRef<PinchZoomRefType | null>(null);
  const pinchZoomRight = useRef<PinchZoomRefType | null>(null);

  const [rotate, setRotate] = useState<number>(0);
  const [zoom, setZoom] = useState<number>(1);

  const onRetargetableEvent = (event: Event) => {
    if (!pinchZoomLeft.current || !pinchZoomRight.current)
      throw Error('Missing pinch-zoom element');
    event.stopPropagation();
    // 将事件传递给PinchZoom组件
    if (event.type === 'wheel') {
      pinchZoomLeft.current._onWheel(event as WheelEvent);
      pinchZoomRight.current._onWheel(event as WheelEvent);
    }
  };

  const onPointerMove = (
    previousPointers: Pointer[],
    changedPointers: Pointer[]
  ) => {
    if (!pinchZoomLeft.current || !pinchZoomRight.current)
      throw Error('Missing pinch-zoom element');
    pinchZoomLeft.current._onPointerMove(previousPointers, changedPointers);
    pinchZoomRight.current._onPointerMove(previousPointers, changedPointers);
  };

  const changeSplitPosition = (position: number) => {
    const $thisEle = twoUpRef.current;
    $splitPoint.set(position);

    requestAnimationFrame(() => {
      $thisEle!.style.setProperty('--split-point', `${position}px`);
    });
  };

  const rotateRight = () => {
    setRotate((rotate) => rotate + 90);
  };
  const rotateLeft = () => {
    setRotate((rotate) => rotate - 90);
  };
  const zoomIn = () => {
    const zoomLevel = 20 / 300;
    setZoom((zoom) => (zoom > 1 ? zoom + zoomLevel : 1 + zoomLevel));
  };
  const zoomOut = () => {
    const zoomLevel = 20 / 300;
    setZoom((zoom) => (zoom > 1 ? 1 - zoomLevel : zoom - zoomLevel));
  };

  useEffect(() => {
    if (!pinchZoomLeft.current || !pinchZoomRight.current)
      throw Error('Missing pinch-zoom element');
    pinchZoomLeft.current._onScale(zoom);
    pinchZoomRight.current._onScale(zoom);
  }, [zoom]);

  useEffect(() => {
    if (!pinchZoomLeft.current || !pinchZoomRight.current)
      throw Error('Missing pinch-zoom element');
    pinchZoomLeft.current._rotate(rotate);
    pinchZoomRight.current._rotate(rotate);
  }, [rotate]);

  useEffect(() => {
    const $thisHandleEle = twoUpHandleRef.current;
    const $thisEle = twoUpRef.current;
    if (!$thisEle || !$thisHandleEle) return;

    const pointAxis = orientation === 'vertical' ? 'clientY' : 'clientX';
    const dimensionAxis = orientation === 'vertical' ? 'height' : 'width';

    const bounds = $thisEle.getBoundingClientRect();
    const boundsAxis = bounds[dimensionAxis];

    const pointerHandleTracker: PointerTracker = new PointerTracker(
      $thisHandleEle,
      {
        start: (_: Pointer[], event: InputEvent) => {
          if (pointerHandleTracker.currentPointers.length === 1) return false;
          event.preventDefault();
          return true;
        },
        move: (previousPointers: Pointer[], changedPointers: Pointer[]) => {
          const pAxis = previousPointers[0][pointAxis];
          const cAxis = changedPointers[0][pointAxis];
          let newPosition = pAxis + (pAxis - cAxis);
          newPosition = Math.max(0, Math.min(newPosition, boundsAxis));
          // setRelativePosition(newPosition / boundsAxis);
          changeSplitPosition(newPosition);
        },
      }
    );

    const pointerTracker: PointerTracker = new PointerTracker($thisEle, {
      start: (_: Pointer[], event: InputEvent) => {
        if (
          pointerTracker.currentPointers.length === 2 ||
          event.target.closest(`.two-up-handle`)
        ) {
          return false;
        }
        event.preventDefault();
        return true;
      },
      move: (previousPointers: Pointer[], changedPointers: Pointer[]) => {
        onPointerMove(previousPointers, changedPointers);
      },
    });

    changeSplitPosition(boundsAxis * 0.5);
  }, [orientation]);

  return (
    <Box
      w="full"
      h="full"
      position="relative"
      ref={twoUpRef}
      sx={{
        '& > .pinch-zoom:nth-of-type(1)': {
          clipPath: 'inset(0 calc(100% - var(--split-point)) 0 0)',
        },
        '& > .pinch-zoom:nth-of-type(2)': {
          clipPath: 'inset(0 0 0 var(--split-point))',
        },
      }}
      onWheelCapture={onRetargetableEvent}
    >
      <PinchZoom ref={pinchZoomLeft}>
        <Image sx={{ willChange: 'auto', flexShrink: 0 }} src={leftImage} />
      </PinchZoom>
      <PinchZoom ref={pinchZoomRight}>
        <Image sx={{ willChange: 'auto', flexShrink: 0 }} src={rightImage} />
      </PinchZoom>
      <Box
        className="two-up-handle"
        ref={twoUpHandleRef}
        sx={{
          height: '100%',
          touchAction: 'none',
          width: '30px',
          transform: 'translateX(var(--split-point)) translateX(-50%)',
          willChange: 'transform',
          cursor: 'ew-resize',
          _before: {
            content: "''",
            display: 'block',
            height: '100%',
            width: '8px',
            margin: '0 auto',
            background: 'blackAlpha.500',
          },
        }}
      >
        <Flex
          sx={{
            placeItems: 'center',
            position: 'absolute',
            top: '50%',
            left: '50%',
            transform: 'translate(-50%, -50%)',
            width: '44px',
            height: '44px',
            background: 'blackAlpha.500',
            borderRadius: '44px',
            padding: '0 8px',
          }}
        >
          <svg viewBox="0 0 27 20">
            <path d="M9.6 0L0 9.6l9.6 9.6z" />
            <path d="M17 19.2l9.5-9.6L16.9 0z" />
          </svg>
        </Flex>
      </Box>
      <ButtonGroup
        position="absolute"
        bottom="10"
        isAttached
        orientation="vertical"
      >
        <IconButton
          icon={<BiZoomIn />}
          aria-label="zoomIn"
          onClick={zoomIn}
          fontSize={20}
        />

        <IconButton
          icon={<BiZoomOut />}
          aria-label="zoomOut"
          onClick={zoomOut}
          fontSize={20}
        />

        <IconButton
          icon={<BiRotateLeft />}
          aria-label="rotateLeft"
          onClick={rotateLeft}
          fontSize={20}
        />

        <IconButton
          icon={<BiRotateRight />}
          aria-label="rotateRight"
          onClick={rotateRight}
          fontSize={20}
        />
      </ButtonGroup>
    </Box>
  );
}
